#include "individual.h"
#include "config.h"

#include <iostream>
#include <cmath>
#include <stdexcept>
#include <cstdlib>
#include <cassert>


//------------------------------------------------------------------------------
// Public functions

Individual::Individual()
    : m_history_bits(I_HISTORY_BITS)
    , m_mutant(false)
{
    // Add the loci required for the game history
    m_loci_count = std::pow(2, m_history_bits + 1);
    // Add the loci to represent the history part of the genes.
    m_loci_count += m_history_bits;

    // If loci count too high, crash me!
    if(m_loci_count > I_MAX_LOCI) {
        // Not enough bits.
        throw std::out_of_range("Not enough loci available for the "
            "desired history size");
    }

    // Initial fitness of 0.
    m_fitness = 0;
}

void Individual::randomizeGenes()
{
    // Set all bits to 0.
    m_genes.reset();

    for (int i = 0; i < m_loci_count; ++i) {
        // Set the bits randomly.
        if((std::rand() % 2) == 1) {
            m_genes.set(i);
        }
    }
}

void Individual::mate(const Individual *p_partner, 
    Individual *&p_child_a,
    Individual *&p_child_b)
{
    int crossover_point;

    // Assert that the history bits are the same size.
    assert(m_history_bits == p_partner->m_history_bits);

    // Create the children.
    p_child_a = new Individual();
    p_child_b = new Individual();

    // Find the crossover point.
    crossover_point = std::rand() % (m_loci_count - 1);

    // Create the genes for the children.
    for(int i = 0; i < m_loci_count; ++i) {
        if(i <= crossover_point) {
            // Place my genes first.
            p_child_a->setGene(i, getGene(i));
            p_child_b->setGene(i, p_partner->getGene(i));
        }
        else {
            // Place my parter's genes first.
            p_child_a->setGene(i, p_partner->getGene(i));
            p_child_b->setGene(i, getGene(i));
        }
    }
}

void Individual::mutate()
{
    int mutated_locus;

    // Choose a random locus to mutate.
    mutated_locus = rand() % m_loci_count;

    // Flip the bit.
    m_genes.flip(mutated_locus);

    // I'm an abomination!
    m_mutant = true;
}

unsigned int Individual::getFitness() const
{
    return m_fitness;
}

void Individual::setFitness(unsigned int p_fitness)
{
    m_fitness = p_fitness;
}


bool Individual::getGene(unsigned int p_loci) const
{
    return m_genes.test(p_loci);
}

void Individual::setGene(unsigned int p_loci, bool p_value)
{
    m_genes.set(p_loci, p_value);
}

unsigned int Individual::getHistorySize() const
{
    // Minimum of 1 game for the history.
    int history_size = 1;

    // Get the history size from our history bits.
    // ... This is defined as the number of '1's in the set.
    for(int i = m_loci_count - m_history_bits;
        i < m_loci_count; ++i) {
        if(m_genes.test(i) == true) {
            // This bit is set.
            ++history_size;
        }
    }

    return history_size;
}

std::string Individual::getGenesAsString() const
{
    return m_genes.to_string<char,std::char_traits<char>,
        std::allocator<char> >();
}

bool Individual::isMutant()
{
    return m_mutant;
}

Individual *Individual::clone()
{
    Individual *i = new Individual();
    
    // Clone me using operator=
    (*i) = *this;

    return i;
}

Individual &Individual::operator=(const Individual &p_i)
{
    m_genes = p_i.m_genes;
    m_history_bits = p_i.m_history_bits;
    m_loci_count = p_i.m_loci_count;
    m_fitness = p_i.m_fitness;

    return *this;
}


//------------------------------------------------------------------------------
// Private Functions
